#include "StdAfx.h"
#include "SgSphere.h"
#include "math.h"
const double PI = 3.141592653589793;

inline void Normalize(GLdouble *v)
{
    GLdouble len = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
    v[0] /= len;
    v[1] /= len;
    v[2] /= len;
}

CSgSphere::CSgSphere(double r)
{
	m_r = r;

	CreateSphere();

}

CSgSphere::~CSgSphere()
{
}


void CSgSphere::CreateSphere()
{
	GLdouble a[] = {1, 0, 0};
    GLdouble b[] = {0, 0, -1};
    GLdouble c[] = {-1, 0, 0};
    GLdouble d[] = {0, 0, 1};
    GLdouble e[] = {0, 1, 0};
    GLdouble f[] = {0, -1, 0};

    int recurse = 5;

	SphereFace(recurse, d, a, e);
    SphereFace(recurse, a, b, e);
    SphereFace(recurse, b, c, e);
    SphereFace(recurse, c, d, e);
    SphereFace(recurse, a, d, f);
    SphereFace(recurse, b, a, f);
    SphereFace(recurse, c, b, f);
    SphereFace(recurse, d, c, f);

}

void CSgSphere::SphereFace(int p_recurse, GLdouble *a, GLdouble *b, GLdouble *c)
{
	if(p_recurse > 1)
	{
		// Compute vectors halfway between the passed vectors
		GLdouble d[3] = {a[0] + b[0], a[1] + b[1], a[2] + b[2]};
		GLdouble e[3] = {b[0] + c[0], b[1] + c[1], b[2] + c[2]};
		GLdouble f[3] = {c[0] + a[0], c[1] + a[1], c[2] + a[2]};

		Normalize(d);
		Normalize(e);
		Normalize(f);

		SphereFace(p_recurse-1, a, d, f);
		SphereFace(p_recurse-1, d, b, e);
		SphereFace(p_recurse-1, f, e, c);
		SphereFace(p_recurse-1, f, d, e);
    }

	GLfloat tx1 = float(atan2(a[0], a[2]) / (2. * PI) +0.5);
	GLfloat ty1 = float(asin(a[1]) / PI + .5);
	AddTexCoord(CGrVector(tx1, ty1));

	AddNormal(a);

	AddVertex(CGrVector(a[0]*m_r, a[1]*m_r, a[2]*m_r));
	
	GLfloat tx = float(atan2(b[0], b[2]) / (2. * PI) + 0.5);
    GLfloat ty = float(asin(b[1]) / PI + .5);
	
	AddTexCoord(CGrVector(tx, ty));
	AddNormal(b);
	AddVertex(CGrVector(b[0]*m_r, b[1]*m_r, b[2]*m_r));

	tx = float(atan2(c[0], c[2]) / (2. * PI) + 0.5);
    ty = float(asin(c[1]) / PI + .5);

	if(tx < 0.75 && tx1 > 0.75)
		tx += 1.0;
    else if(tx > 0.75 && tx1 < 0.75)
		tx -= 1.0;

	AddTexCoord(CGrVector(tx, ty));
	AddNormal(c);
	AddVertex(CGrVector(c[0]*m_r, c[1]*m_r, c[2]*m_r));
}

void CSgSphere::Render()
{
	if(!m_Texture.Empty() )
	{
		 glEnable(GL_TEXTURE_2D);
		 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		 glBindTexture(GL_TEXTURE_2D, m_Texture.TexName());
	}

	glBegin(GL_TRIANGLES);
	// iterate through all vertices
    for(unsigned k = 0; k < m_vertices.size(); k++)
    {
		// added bounds checking and texture coordinates support

		if (m_normals.size() > (unsigned)k)
			glNormal3dv(m_normals[k]);

		if (m_tvertices.size() > (unsigned)k)
			glTexCoord2dv(m_tvertices[k]);

		glVertex3dv(m_vertices[k]);
    }
    glEnd();

	if( !m_Texture.Empty() )
		glDisable( GL_TEXTURE_2D );
}

